package nancal.mp.db.mongo.entity.dev

import nancal.mp.db.mongo.*
import nbcp.base.comm.MvnDependencyBasicData
import nbcp.base.db.annotation.Cn
import nbcp.base.db.annotation.DbEntityGroup
import nbcp.base.db.annotation.DbEntityIndex
import nbcp.base.db.annotation.DbEntityIndexes
import nbcp.base.extend.HasValue
import nbcp.base.extend.Slice
import nbcp.base.model.BaseMarkEntity
import nbcp.base.utils.WebUtil
import org.springframework.data.mongodb.core.mapping.Document

@Document
@DbEntityIndexes(DbEntityIndex("code", unique = true))
@DbEntityGroup("dev")
@Cn("应用部署设置服务器")
data class AppDeploySetting(
    var code: String = "",
    var name: String = "",

    var corpName: String = "",
    var corpLogo: String = "",
    var corpIcon: String = "",
    /**
     * 系统名称，登录页显示
     */
    var systemName: String = "",
    /**
     * 登录页面，使用哪个登录页
     */
    var loginPage: String = "",
    var jenkinsServer: JenkinsServer = JenkinsServer(),
    var k8sConfig: K8sConfig = K8sConfig(),

    /**
     * 中台地址
     */
    var mpIntegrationApiHost: String = "",

    /**
     * 中台地址的token = app.admin-token
     */
    var adminToken: String = "",

    var nexusServer: NexusServerConfig = NexusServerConfig(),

    var dockerBuildHosts: List<HostIP> = listOf(),

    var packageTool: PackageToolEnum = PackageToolEnum.Yarn,

    /**
     * maven Setting.conf 文件中的 镜像地址。 如果不存在，使用私服配置
     */
//    var mavenMirror: String = "",

    @Cn("Harbor域名")
    var harborServer: HarborServerConfig = HarborServerConfig(),
    var pipelineTemplate: PipelineTemplateEnum = PipelineTemplateEnum.K8s,
    var dockerApiUrl: String = "",

    /**
     * 当前环境， == Profile
     */
    var profile: String = "",
    var clusterDeployEnv: MicroServiceDeployEnvEnum = MicroServiceDeployEnvEnum.boot,

//    @Cn("资源地址") var resourceFileUrl: String = "",
    @Cn("部署语言设置")
    var languageSettings: List<DeployLanguageSetting> = getDefaultDeployLanguageSetting(),


    var javaOpts: String = "",
    var javaArgs: String = "",


    var serviceNameStyle: ServiceNameStyleEnum = ServiceNameStyleEnum.ProductLineCodeLanguage,

    var snapshotVersionAction: SnapshotVersionActionEnum = SnapshotVersionActionEnum.Ignore,

    /**
     * Docker容器中设置时区
     */
    var dockerEnvTimezone: String = "Asia/Shanghai",
    /**
     * 编译时删除 yarn.lock
     */
    var removeNpmLock: Boolean = false,

    var remark: String = "",
    var isActive: Boolean = false
) : BaseMarkEntity() {

    companion object {
        fun getDefaultDeployLanguageSetting(): List<DeployLanguageSetting> {
            return listOf(
                DeployLanguageSetting(
                    JenkinsLanguageEnum.Java,
                    mutableListOf(AffinitySetting("**", true, "api"))
                ),
                DeployLanguageSetting(JenkinsLanguageEnum.Vue,
                    mutableListOf(AffinitySetting("**", true, "api"))
                ),
                DeployLanguageSetting(JenkinsLanguageEnum.Node,
                    mutableListOf(AffinitySetting("**", true, "api"))
                ),
                DeployLanguageSetting(JenkinsLanguageEnum.Nuxt,
                    mutableListOf(AffinitySetting("**", true, "api"))
                ),
                DeployLanguageSetting(JenkinsLanguageEnum.Python,
                    mutableListOf(AffinitySetting("**", true, "api"))
                ),
                DeployLanguageSetting(JenkinsLanguageEnum.Php,
                    mutableListOf(AffinitySetting("**", true, "api"))
                )
            );
        }
    }

    val sudo: String
        get() {
            if (this.jenkinsServer.useSudo) {
                return "sudo -E "
            }

            return ""
        }

    val mpIntegrationApiUrl: String
        get() {
            return WebUtil.getFullHttpUrl(mpIntegrationApiHost)
        }

    /**
     * docker --add-host 参数
     */
    val dockerBuildAddHostsParameters: String
        get() {
            return this.dockerBuildHosts.map { " --add-host ${it.host}:${it.ip} " }.joinToString(" ")
        }


    fun getLanguageSetting(language: JenkinsLanguageEnum): DeployLanguageSetting {
        return this.languageSettings
            .first { it.language == language }
    }

    fun getLanguageVersionSetting(language: JenkinsLanguageEnum, languageVersion: String): LanguageVersionSetting {
        return this.languageSettings
            .first { it.language == language }
            .languageVersionSettings
            .first { it.languageVersion == languageVersion }
    }

    fun getBuildImageFullName(language: JenkinsLanguageEnum, languageVersion: String): String {
        return this.harborServer.getHarborToolImagePrefix() + getLanguageVersionSetting(
            language,
            languageVersion
        ).buildImage
    }


    fun getRunImageFullName(language: JenkinsLanguageEnum, languageVersion: String): String {
        return this.harborServer.getHarborToolImagePrefix() + getLanguageVersionSetting(
            language,
            languageVersion
        ).runImage
    }


    fun getOpsBaseBashImage(): String {
        return this.harborServer.getHarborToolImagePrefix() + this.harborServer.bashImageName
    }


    fun getOpsNginxImage(): String {
        return this.harborServer.getHarborToolImagePrefix() + this.harborServer.nginxImageName;
    }
}


data class AffinitySetting(
    /**
     * AntPathMatcher 的模式匹配
     */
    var antPathMatcher: String = "",
    var inOrNot: Boolean = false,
    var nodeRole: String = ""
)

data class ResourceSetting(
    /**
     * AntPathMatcher 的模式匹配
     */
    var antPathMatcher: String = "",

    var cpus: Int? = null,
    var requestMemory: Int? = null,
    var maxMemory: Int? = null
)

data class HostIP(var host: String = "", var ip: String = "")


open class LanguageVersionSetting(
    var languageVersion: String = "",
    var buildImage: String = "",
    var runImage: String = "",
    var deploymentYaml: String = ""
)

//class DockerLanguageImage(
//    var language: JenkinsLanguageEnum = JenkinsLanguageEnum.Java,
//    languageVersion: String = "",
//      buildImage: String = "",
//      runImage: String = "",
//) : DockerImageData(languageVersion, buildImage,runImage)

data class DeployLanguageSetting(
    var language: JenkinsLanguageEnum = JenkinsLanguageEnum.Java,

    var affinitySettings: MutableList<AffinitySetting> = mutableListOf(),

//    var resourceSettings: MutableList<ResourceSetting> = mutableListOf(),

    /**
     * 编译前钩子
     */
    var preBuild: String = "",
    /**
     * 编译后钩子
     */
    var postBuild: String = "",

    /**
     * 部署前钩子
     */
    var preDeploy: String = "",

    /**
     * 部署后钩子
     */
    var postDeploy: String = "",

    var dockerfile: String = "",
    var deploymentYaml: String = "",
    var serviceYaml: String = "",

    /**
     * 不同语言版本的设置
     */
    var languageVersionSettings: MutableList<LanguageVersionSetting> = mutableListOf()

) {
}

data class NexusServerConfig(
    /**
     * 可能是完整的地址。也可以不包含 http
     */
    var hostUrl: String = "",
    var userName: String = "admin",
    var password: String = "",
) {
    var email: String = ""
        get() {
            if (field.isEmpty()) {
                return this.userName + "@nexus.com"
            }
            return field;
        }
        set(value: String) {
            field = value;
        }

    val nexusHttpUrl: String
        get() {
            return WebUtil.getFullHttpUrl(hostUrl).trimEnd('/')
        }
    val nexusWithoutHttpUrl: String
        get() {
            var index = nexusHttpUrl.indexOf("://");
            return nexusHttpUrl.Slice(index + 1);
        }
}

open class SshServerConfig(
    var host: String = "",
    var userName: String = "root",
    var password: String = "",
    var sshPort: Int = 22,
)

data class HarborServerConfig(
    var isHttps: Boolean = true,
    var host: String = "",
    var userName: String = "admin",
    var password: String = ""
) {
    var bashImageName: String = "ops-bash"
    var nginxImageName: String = "nginx"

    fun getHarborImagePrefix(language: JenkinsLanguageEnum): String {
        if (this.host.HasValue) {
            return host + "/${language.toString().lowercase()}/"
        }
        return "";
    }

    fun getHarborToolImagePrefix(): String {
        if (this.host.HasValue) {
            return host + "/tools/";
        }
        return "";
    }

}

open class MavenJarDefine() : MvnDependencyBasicData() {

    fun isEmpty(): Boolean {
        if (this.groupId.isEmpty() || this.artifactId.isEmpty()) {
            return true;
        }

        return false;
    }
}

data class JenkinsServer(
    /**
     * 可能是完整的地址。也可以不包含 http
     */
    @Cn("地址") var hostUrl: String = "",
    var userName: String = "admin",
    var password: String = "",
    var useSudo: Boolean = true,
    var usePipeline: Boolean = true
) {

    var runInDocker: Boolean = false

    /**
     * 比较安全的做法是：挂载路径内外一致， 即  -v <el-tag>/var/jenkins_home</el-tag>:/var/jenkins_home <br/>
     * 如果Jenkins挂载了宿主机Docker，且挂载路径内外不一到处， 就一定要配置 jenkins_home 在宿主机的的目录 <br/>
     * 否则，把该字段置空。 <br/>
     * 原因分析：<br/>
     * 如果挂载内外不一致， 如 -v <el-tag>/opt/jenkins/jenkins_home</el-tag>:/var/jenkins_home 。 在 Jeinkins 内部运行 focker ，如这样： <br />
     * docker run -v $pwd/code:/code  ops git-get.sh <br />
     * 那么jenkins里的实际命令是  docker run -v /var/jenkins_home/workspace/xxx/code:/code  ops git-get.sh <br />
     * 而真正执行docker命令的却是宿主机，到宿主机正确的命令应该是： docker run -v <el-tag>/opt/jenkins/jenkins_home</el-tag>/workspace/xxx/code:/code  ops git-get.sh   <br />
     * 所以在真正挂载的时候，就要根据宿主机挂载目录做一个转换，转换函数是： <br/>
     * $pwd 要转换为： <el-tag>/opt/jenkins/jenkins_home</el-tag> + <el-tag> docker中 $pwd 路径去除  /var/jenkins_home 部分</el-tag>
     */
    var jenkinsHomePathMountToDocker: String = "/opt/jenkins/jenkins_home"
        get() {
            if (runInDocker) {
                return field;
            }

            return "";
        }
        set(value) {
            field = value;
        }

    var executor: DeployExecutorEnum = DeployExecutorEnum.Jenkins

    /**
     * shell 表示当前路径
     */
    val currentRealJenkinsShellPath: String
        get() {
            return "${jenkinsHomePathMountToDocker}${'$'}{PWD:17}"
        }
    val jenkinsHttpUrl: String
        get() {
            return WebUtil.getFullHttpUrl(hostUrl);
        }
}


data class K8sConfig(
    var apiServerHost: String = "",
    var apiToken: String = "",
    var kubeConfigContent: String = "",

    var enableIstio: Boolean = false,
    var devUserIfIstio: String = "",
    var mountConfigmap: Boolean = false,
) {
    val apiServerUrl: String
        get() {
            return WebUtil.getFullHttpUrl(apiServerHost);
        }
}